﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;

namespace BSU.GraduateWork.Web.Controls.Menu
{
    public class Menu
    {
        private const string ActionNameAttribute = "actionName";
        private const string ControllerNameAttribute = "controllerName";
        private string MenuCssClass = "menu";
        private string ActiveNodeCssClass = "active";

        private ViewContext _viewContext;
        private SiteMapProvider _provider;

        public string SiteMapProvider { get; set; }

        public SiteMapProvider Provider
        {
            get
            {
                if (_provider == null)
                {
                    if (String.IsNullOrEmpty(SiteMapProvider))
                    {
                        _provider = SiteMap.Provider;
                    }
                    else
                    {
                        _provider = SiteMap.Providers[SiteMapProvider];
                    }
                }
                return _provider;
            }
            set
            {
                _provider = value;
            }
        }

        public Menu(ViewContext viewContext)
        {
            _viewContext = viewContext;
        }

        public Menu(ViewContext viewContext, string siteMapProvider)
        {
            _viewContext = viewContext;

            SiteMapProvider = siteMapProvider;
        }

        public Menu(ViewContext viewContext, string siteMapProvider, string menuCssClass, string activeNodeCssClass)
        {
            _viewContext = viewContext;

            SiteMapProvider = siteMapProvider;
            MenuCssClass = menuCssClass;
            ActiveNodeCssClass = activeNodeCssClass;
        }

        public override string ToString()
        {
            if (Provider == null)
            {
                return null;
            }
            var rootNode = Provider.RootNode;
            if (rootNode != null)
            {
                return CreateNodes(rootNode.ChildNodes, MenuCssClass);
            }

            return null;
        }

        private string CreateNodes(SiteMapNodeCollection nodes, string cssClass)
        {
            var builder = new StringBuilder();
            if (nodes != null && nodes.Count > 0)
            {
                builder.Append("<ul");
                if (!String.IsNullOrEmpty(cssClass))
                {
                    builder.AppendFormat(" class='{0}'", cssClass);
                }
                builder.Append(">");
                foreach (SiteMapNode node in nodes)
                {
                    builder.Append("<li");

                    var cssClassBuilder = new StringBuilder();

                    if (IsCurrentController(node))
                    {
                        cssClassBuilder.Append(ActiveNodeCssClass);
                    }
                    if (cssClassBuilder.Length > 0)
                    {
                        builder.AppendFormat(" class='{0}'", cssClassBuilder);
                    }

                    builder.Append(">");

                    builder.AppendFormat("<a href='{0}'>{1}</a>", GetNodeUrl(node), node.Title);
                    builder.Append(CreateNodes(node.ChildNodes, null));
                    builder.Append("</li>");
                }
                builder.Append("</ul>");
            }
            return builder.ToString();
        }

        private bool IsCurrentAction(SiteMapNode node)
        {
            string actionName = node[ActionNameAttribute];

            string currentActionName = (string)_viewContext.RouteData.Values["action"];

            if (IsCurrentController(node) && currentActionName.Equals(actionName, StringComparison.CurrentCultureIgnoreCase))
                return true;

            return false;
        }

        private bool IsCurrentController(SiteMapNode node)
        {
            string controllerName = node[ControllerNameAttribute];

            string currentControllerName = (string)_viewContext.RouteData.Values["controller"];

            if (currentControllerName.Equals(controllerName, StringComparison.CurrentCultureIgnoreCase))
                return true;

            return false;
        }

        private string GetNodeUrl(SiteMapNode node)
        {
            string actionName = node[ActionNameAttribute];
            string controllerName = node[ControllerNameAttribute];

            if (!String.IsNullOrEmpty(actionName) && !String.IsNullOrEmpty(controllerName))
            {
                var urlHelper = new UrlHelper(_viewContext.RequestContext);
                return urlHelper.Action(actionName, controllerName);
            } if (node.Url == String.Empty)
            {
                return "javascript:function(){return false;}";
            }
            return node.Url;
        }

        private bool IsNodeActive(SiteMapNode node)
        {
            if (IsCurrentController(node))
            {
                return true;
            }

            foreach (SiteMapNode child in node.ChildNodes)
            {
                if (IsCurrentController(child))
                {
                    return true;
                }
            }
            return false;
        }
    }
}